package net.risesoft.api.org;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import net.risesoft.entity.Y9Department;
import net.risesoft.entity.Y9DepartmentProp;
import net.risesoft.entity.Y9Group;
import net.risesoft.entity.Y9OrgBase;
import net.risesoft.entity.Y9Person;
import net.risesoft.entity.Y9Position;
import net.risesoft.enums.Y9DepartmentPropCategoryEnum;
import net.risesoft.manager.Y9OrgBaseManager;
import net.risesoft.model.Department;
import net.risesoft.model.DepartmentProp;
import net.risesoft.model.Group;
import net.risesoft.model.OrgUnit;
import net.risesoft.model.Person;
import net.risesoft.model.Position;
import net.risesoft.service.org.Y9DepartmentPropService;
import net.risesoft.service.org.Y9DepartmentService;
import net.risesoft.service.org.Y9GroupService;
import net.risesoft.service.org.Y9PersonService;
import net.risesoft.service.org.Y9PositionService;
import net.risesoft.util.ModelConvertUtil;
import net.risesoft.y9.Y9LoginUserHolder;
import net.risesoft.y9.util.Y9BeanUtil;

/**
 * 部门服务组件
 *
 * @author dingzhaojun
 * @author qinman
 * @author mengjuhua
 * @date 2022/2/10
 * @since 9.6.0
 */
@Primary
@RestController
@RequestMapping(value = "/services/rest/department", produces = MediaType.APPLICATION_JSON_VALUE)
@Slf4j
@RequiredArgsConstructor
public class DepartmentApiImpl implements DepartmentApi {

    private final Y9OrgBaseManager y9OrgBaseManager;
    private final Y9DepartmentService y9DepartmentService;
    private final Y9GroupService y9GroupService;
    private final Y9PersonService y9PersonService;
    private final Y9PositionService y9PositionService;
    private final Y9DepartmentPropService y9DepartmentPropService;

    /**
     * 新建部门
     *
     * @param tenantId       租户id
     * @param departmentJson 部门JSON字符串
     * @return Department 部门对象
     * @since 9.6.0
     */
    @Override
    @PostMapping("/createDepartment")
    public Department createDepartment(@RequestParam String tenantId, @RequestParam String departmentJson) {
        Y9LoginUserHolder.setTenantId(tenantId);
        ObjectMapper om = new ObjectMapper();
        try {
            JsonNode jn = om.readTree(departmentJson);
            om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            SimpleDateFormat myFmt2 = new SimpleDateFormat("yyyy-MM-dd");
            om.setDateFormat(myFmt2);
            Y9Department y9Department = om.readValue(jn.toString(), Y9Department.class);
            y9Department = y9DepartmentService.saveOrUpdate(y9Department, y9OrgBaseManager.getParent(y9Department.getParentId()));
            return ModelConvertUtil.convert(y9Department, Department.class);
        } catch (JsonProcessingException e) {
            LOGGER.warn(e.getMessage(), e);
            return null;
        }
    }

    /**
     * 删除部门
     *
     * @param departmentId 部门id
     * @param tenantId     租户id
     * @return boolean 是否删除成功
     * @since 9.6.0
     */
    @Override
    @GetMapping("/deleteDepartment")
    public boolean deleteDepartment(@RequestParam String tenantId, @RequestParam String departmentId) {
        Y9LoginUserHolder.setTenantId(tenantId);

        return y9DepartmentService.setDepartmentDeleted(departmentId);
    }

    /**
     * 禁用部门
     *
     * @param tenantId     租户id
     * @param departmentId 部门id
     * @return true：禁用成功，false：禁用失败
     * @since 9.6.0
     */
    @Override
    @GetMapping("/disableDepartment")
    public boolean disableDepartment(@RequestParam String tenantId, @RequestParam String departmentId) {
        if (StringUtils.isBlank(tenantId) || StringUtils.isBlank(departmentId)) {
            return false;
        }

        Y9LoginUserHolder.setTenantId(tenantId);

        Y9Department y9Department = y9DepartmentService.getById(departmentId);
        if (y9Department != null && y9Department.getId() != null) {
            y9Department.setDisabled(true);
            y9DepartmentService.save(y9Department);
            return true;
        }

        return false;
    }

    /**
     * 获取委办局
     *
     * @param tenantId     租户id
     * @param departmentId 部门id
     * @return OrgUnit 组织机构节点对象
     * @since 9.6.0
     */
    @Override
    @GetMapping("/getBureau")
    public OrgUnit getBureau(@RequestParam String tenantId, @RequestParam String departmentId) {
        Y9LoginUserHolder.setTenantId(tenantId);
        Y9OrgBase bureau = y9OrgBaseManager.getBureau(departmentId);
        return ModelConvertUtil.orgBaseToOrgUnit(bureau);
    }

    /**
     * 根据id获得部门对象
     *
     * @param tenantId     租户id
     * @param departmentId 部门唯一标识
     * @return Department 部门对象
     * @since 9.6.0
     */
    @Override
    @GetMapping("/getDepartment")
    public Department getDepartment(@RequestParam String tenantId, @RequestParam String departmentId) {
        Y9LoginUserHolder.setTenantId(tenantId);
        Y9Department y9Department = y9DepartmentService.findById(departmentId);
        return ModelConvertUtil.convert(y9Department, Department.class);
    }

    /**
     * 获取部门父节点
     *
     * @param tenantId     租户id
     * @param departmentId 部门唯一标识
     * @return OrgUnit 组织机构节点对象
     * @since 9.6.0
     */
    @Override
    @GetMapping("/getParent")
    public OrgUnit getParent(@RequestParam String tenantId, @RequestParam String departmentId) {
        Y9LoginUserHolder.setTenantId(tenantId);
        Y9Department orgDept = y9DepartmentService.getById(departmentId);
        if (orgDept == null) {
            return null;
        }
        Y9OrgBase parent = y9OrgBaseManager.getParent(orgDept.getParentId());
        return ModelConvertUtil.orgBaseToOrgUnit(parent);
    }

    /**
     * 获取部门下的所有人员(递归，包含部门下对应的人员)
     *
     * @param tenantId     租户id
     * @param departmentId 部门id
     * @return List<Person> 人员对象集合
     * @since 9.6.0
     */
    @Override
    @GetMapping("/listAllPersons")
    public List<Person> listAllPersons(@RequestParam String tenantId, @RequestParam String departmentId) {
        Y9LoginUserHolder.setTenantId(tenantId);
        List<Y9Person> orgPersonList = y9OrgBaseManager.listAllPersonsRecursionDownward(departmentId);
        List<Person> personList = new ArrayList<>();
        for (Y9Person y9Person : orgPersonList) {
            Person person = ModelConvertUtil.convert(y9Person, Person.class);
            if (!personList.contains(person)) {
                personList.add(person);
            }
        }
        return personList;
    }

    /**
     * 获取部门下的所有未禁用/禁用的人员(递归)
     *
     * @param tenantId     租户id
     * @param departmentId 部门id
     * @param disabled     是否禁用
     * @return List<Person> 人员对象集合
     * @since 9.6.0
     */
    @Override
    @GetMapping("/listAllPersonsByDisabled")
    public List<Person> listAllPersonsByDisabled(@RequestParam String tenantId, @RequestParam String departmentId, @RequestParam Boolean disabled) {
        Y9LoginUserHolder.setTenantId(tenantId);
        List<Y9Person> orgPersonList = y9OrgBaseManager.listAllPersonsRecursionDownward(departmentId, disabled);
        List<Person> personList = new ArrayList<>();
        for (Y9Person y9Person : orgPersonList) {
            personList.add(ModelConvertUtil.convert(y9Person, Person.class));
        }
        return personList;
    }

    /**
     * 根据是否禁用，人员姓名获取部门下所有人员
     *
     * @param tenantId     租户id
     * @param departmentId 部门id
     * @param disabled     是否禁用
     * @param name         人员姓名
     * @return List<Person> 人员对象集合
     * @since 9.6.0
     */
    @Override
    @GetMapping("/listAllPersonsByDisabledAndName")
    public List<Person> listAllPersonsByDisabledAndName(@RequestParam String tenantId, @RequestParam String departmentId, @RequestParam Boolean disabled, @RequestParam String name) {
        Y9LoginUserHolder.setTenantId(tenantId);
        List<Y9Person> orgPersonList = y9OrgBaseManager.searchAllPersonsRecursionDownward(departmentId, disabled, name);
        List<Person> personList = new ArrayList<>();
        for (Y9Person y9Person : orgPersonList) {
            personList.add(ModelConvertUtil.convert(y9Person, Person.class));
        }
        return personList;
    }

    /**
     * 根据租户id和路径获取所有部门对象
     *
     * @param tenantId 租户id
     * @param dn       路径
     * @return List<Department> 部门对象集合
     * @since 9.6.0
     */
    @Override
    @GetMapping("/listByDn")
    public List<Department> listByDn(@RequestParam String tenantId, @RequestParam String dn) {
        Y9LoginUserHolder.setTenantId(tenantId);
        List<Y9Department> list = y9DepartmentService.listByDn(dn);
        List<Department> list2 = new ArrayList<>();
        for (Y9Department department : list) {
            list2.add(ModelConvertUtil.convert(department, Department.class));
        }
        return list2;
    }

    /**
     * 根据组织节点id查找管理的部门部门属性配置
     *
     * @param tenantId  租户id
     * @param orgBaseId 组织节点id
     * @param category  配置类型 {@link Y9DepartmentPropCategoryEnum}
     * @return
     * @since 9.6.0
     */
    @Override
    @GetMapping("/listByOrgBaseIdAndCategory")
    public List<DepartmentProp> listByOrgBaseIdAndCategory(@RequestParam String tenantId, @RequestParam String orgBaseId, @RequestParam Integer category) {
        if (StringUtils.isBlank(tenantId) || StringUtils.isBlank(orgBaseId)) {
            return new ArrayList<>();
        }
        Y9LoginUserHolder.setTenantId(tenantId);

        List<Y9DepartmentProp> y9DepartmentPropList = y9DepartmentPropService.listByOrgBaseIdAndCategory(orgBaseId, category);
        List<DepartmentProp> departmentPropList = new ArrayList<>();
        DepartmentProp departmentProp = null;
        for (Y9DepartmentProp y9DepartmentProp : y9DepartmentPropList) {
            departmentProp = new DepartmentProp();
            Y9BeanUtil.copyProperties(y9DepartmentProp, departmentProp);
            departmentPropList.add(departmentProp);
        }
        return departmentPropList;
    }

    /**
     * 根据部门名称，模糊查询部门列表
     *
     * @param tenantId 租户id
     * @param deptName 部门名称
     * @return
     * @since 9.6.0
     */
    @Override
    @GetMapping("/listByTenantIdAndDeptName")
    public List<Department> listByTenantIdAndDeptName(@RequestParam String tenantId, @RequestParam String deptName) {
        Y9LoginUserHolder.setTenantId(tenantId);
        try {
            List<Y9Department> list = y9DepartmentService.listByNameLike(deptName);
            List<Department> list2 = new ArrayList<>();
            for (Y9Department o : list) {
                list2.add(ModelConvertUtil.convert(o, Department.class));
            }
            return list2;
        } catch (Exception e) {
            LOGGER.warn(e.getMessage(), e);
        }
        return Collections.emptyList();
    }

    /**
     * 获得一组部门对象
     *
     * @param tenantId 租户id
     * @param ids      部门唯一标识结合
     * @return List&lt;Department&gt; 部门对象集合
     * @since 9.6.0
     */
    @Override
    @GetMapping("/listDepartments")
    public List<Department> listDepartments(@RequestParam String tenantId, @RequestParam List<String> ids) {
        Y9LoginUserHolder.setTenantId(tenantId);
        List<Department> deptList = new ArrayList<>();
        for (String id : ids) {
            deptList.add(getDepartment(tenantId, id));
        }
        return deptList;
    }

    /**
     * 获取用户组(下一级)
     *
     * @param tenantId     租户id
     * @param departmentId 部门唯一标识
     * @return List<Group> 用户组对象集合
     * @since 9.6.0
     */
    @Override
    @GetMapping("/listGroups")
    public List<Group> listGroups(@RequestParam String tenantId, @RequestParam String departmentId) {
        List<Y9Group> orgGroupList = y9GroupService.listByParentId(departmentId);
        List<Group> groupList = new ArrayList<>();
        for (Y9Group y9Group : orgGroupList) {
            groupList.add(ModelConvertUtil.convert(y9Group, Group.class));
        }
        return groupList;
    }

    /**
     * 获取部门领导
     *
     * @param tenantId     租户id
     * @param departmentId 部门唯一标识
     * @return List<OrgUnit> 人员对象集合
     * @since 9.6.0
     */
    @Override
    @GetMapping("/listLeaders")
    public List<OrgUnit> listLeaders(@RequestParam String tenantId, @RequestParam String departmentId) {
        Y9LoginUserHolder.setTenantId(tenantId);
        List<OrgUnit> orgUnitList = new ArrayList<>();
        List<Y9OrgBase> y9OrgBaseList = y9DepartmentService.listLeaders(departmentId);
        OrgUnit orgUnit = null;
        for (Y9OrgBase y9OrgBase : y9OrgBaseList) {
            orgUnit = new OrgUnit();
            Y9BeanUtil.copyProperties(y9OrgBase, orgUnit);
            orgUnitList.add(orgUnit);
        }
        return orgUnitList;
    }

    /**
     * 获取部门主管领导
     *
     * @param tenantId     租户id
     * @param departmentId 部门唯一标识
     * @return List<OrgUnit> 人员对象集合
     * @since 9.6.0
     */
    @Override
    @GetMapping("/listManagers")
    public List<OrgUnit> listManagers(@RequestParam String tenantId, @RequestParam String departmentId) {
        Y9LoginUserHolder.setTenantId(tenantId);
        List<OrgUnit> orgUnitList = new ArrayList<>();
        List<Y9OrgBase> y9OrgBaseList = y9DepartmentService.listManagers(departmentId);
        for (Y9OrgBase y9OrgBase : y9OrgBaseList) {
            orgUnitList.add(ModelConvertUtil.orgBaseToOrgUnit(y9OrgBase));
        }
        return orgUnitList;
    }

    /**
     * 获取部门下的未删除的人员(下一级)
     *
     * @param tenantId     租户id
     * @param departmentId 部门唯一标识
     * @return List<Person> 岗位对象集合
     * @since 9.6.0
     */
    @Override
    @GetMapping("/listPersons")
    public List<Person> listPersons(@RequestParam String tenantId, @RequestParam String departmentId) {
        Y9LoginUserHolder.setTenantId(tenantId);
        List<Y9Person> orgPersonList = new CopyOnWriteArrayList<>();
        orgPersonList.addAll(y9PersonService.listByParentId(departmentId));
        List<Person> personList = new ArrayList<>();
        for (Y9Person y9Person : orgPersonList) {
            Person person = ModelConvertUtil.convert(y9Person, Person.class);
            if (!personList.contains(person)) {
                personList.add(person);
            }
        }
        return personList;
    }

    /**
     * 获取部门下的未禁用/禁用的人员(下一级)
     *
     * @param tenantId     租户id
     * @param departmentId 部门id
     * @param disabled     是否禁用
     * @return List<Person> 人员对象集合
     * @since 9.6.0
     */
    @Override
    @GetMapping("/listPersonsByDisabled")
    public List<Person> listPersonsByDisabled(@RequestParam String tenantId, @RequestParam String departmentId, @RequestParam Boolean disabled) {
        Y9LoginUserHolder.setTenantId(tenantId);

        List<Y9Person> orgPersonList = new CopyOnWriteArrayList<>();
        orgPersonList.addAll(y9PersonService.listByParentIdAndDisabled(departmentId, disabled));
        List<Person> personList = new ArrayList<>();
        for (Y9Person y9Person : orgPersonList) {
            Person person = ModelConvertUtil.convert(y9Person, Person.class);
            if (!personList.contains(person)) {
                personList.add(person);
            }
        }
        return personList;
    }

    /**
     * 获取岗位(下一级)
     *
     * @param tenantId     租户id
     * @param departmentId 部门唯一标识
     * @return List<Position> 岗位对象集合
     * @since 9.6.0
     */
    @Override
    @GetMapping("/listPositions")
    public List<Position> listPositions(@RequestParam String tenantId, @RequestParam String departmentId) {
        Y9LoginUserHolder.setTenantId(tenantId);
        List<Y9Position> orgPositionList = y9PositionService.listByParentId(departmentId);
        List<Position> positionList = new ArrayList<>();
        for (Y9Position y9Position : orgPositionList) {
            positionList.add(ModelConvertUtil.convert(y9Position, Position.class));
        }
        return positionList;
    }

    /**
     * 获取子部门(下一级)
     *
     * @param tenantId     租户id
     * @param departmentId 部门唯一标识
     * @return List<Department> 部门对象集合
     * @since 9.6.0
     */
    @Override
    @GetMapping("/listSubDepartments")
    public List<Department> listSubDepartments(@RequestParam String tenantId, @RequestParam String departmentId) {
        Y9LoginUserHolder.setTenantId(tenantId);
        List<Y9Department> orgDeptList = y9DepartmentService.listByParentId(departmentId);
        List<Department> deptList = new ArrayList<>();
        for (Y9Department orgDept : orgDeptList) {
            deptList.add(ModelConvertUtil.convert(orgDept, Department.class));
        }
        return deptList;
    }

    /**
     * 保存部门
     *
     * @param tenantId       租户id
     * @param departmentJson 部门json
     * @return Department 部门对象
     * @since 9.6.0
     */
    @Override
    @PostMapping("/saveDepartment")
    public Department saveDepartment(@RequestParam String tenantId, @RequestParam String departmentJson) {
        Y9LoginUserHolder.setTenantId(tenantId);
        ObjectMapper om = new ObjectMapper();
        try {
            JsonNode jn = om.readTree(departmentJson);
            om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            SimpleDateFormat myFmt2 = new SimpleDateFormat("yyyy-MM-dd");
            om.setDateFormat(myFmt2);
            Y9Department y9Department = om.readValue(jn.toString(), Y9Department.class);
            y9Department = y9DepartmentService.saveOrUpdate(y9Department, y9OrgBaseManager.getParent(y9Department.getParentId()));
            return ModelConvertUtil.convert(y9Department, Department.class);
        } catch (JsonProcessingException e) {
            LOGGER.warn(e.getMessage(), e);
            return null;
        }
    }

    /**
     * 根据条件查询部门对象
     *
     * @param tenantId    租户id
     * @param whereClause sql语句where后面的条件语句
     * @return List<Department> 部门对象集合
     * @since 9.6.0
     */
    @Override
    @GetMapping("/search")
    public List<Department> search(@RequestParam String tenantId, @RequestParam String whereClause) {
        Y9LoginUserHolder.setTenantId(tenantId);
        List<Y9Department> orgDepartmentList = y9DepartmentService.search(whereClause);

        Collections.sort(orgDepartmentList);
        List<Department> departmentList = new ArrayList<>();
        for (Y9Department y9Department : orgDepartmentList) {
            departmentList.add(ModelConvertUtil.convert(y9Department, Department.class));
        }
        return departmentList;
    }
}
